// i.d(t, { c: () => FloorsViewData })
import AnimatedNumber from "../object/AnimatedNumber"
import Data from "../object/Data"
import LangKey from "../constant/lang.key"
import ObservableValue from "../observer/observable.value"

import ObservableMap from "../observer/observable.map"
import ObservableArray from "../observer/observable.array"
import { appTypeMin } from "../enum/appType.enum"
import FloorState from "../object/FloorState"
import sweepAlignmentEnum from "../enum/sweepAlignment.enum"
import { ISubscription } from "../observer/observable"
class FloorsStateHelper {
  floors: FloorsData
  viewmodeData: ViewmodeData
  sweepData: SweepData
  applicationData: ApplicationData
  currentFloorObservable: ObservableValue<Floor>
  bindings: (Subscription | ISubscription)[]
  states: ObservableMap<FloorState>
  _navigableFloorIds: ObservableArray<string>
  hasEnabledAlignedSweeps: boolean
  constructor(floors: FloorsData, viewmodeData: ViewmodeData, sweepData: SweepData, applicationData: ApplicationData, floor: ObservableValue<Floor>) {
    this.floors = floors
    this.viewmodeData = viewmodeData
    this.sweepData = sweepData
    this.applicationData = applicationData
    this.currentFloorObservable = floor
    this.bindings = []
    this.states = new ObservableMap()
    this._navigableFloorIds = new ObservableArray()
    this.hasEnabledAlignedSweeps = !1
    this.bindings.push(
      viewmodeData.makeModeChangeSubscription(this.updateHidden.bind(this)),
      sweepData.makeSweepChangeSubscription(this.updateHidden.bind(this)),
      floor.onChanged(this.updateHidden.bind(this)),
      viewmodeData.makeModeChangeSubscription(this.updateNavigable.bind(this)),
      sweepData.makeSweepChangeSubscription(this.updateNavigable.bind(this)),
      applicationData.onPropertyChanged("application", this.updateFloorSweepData.bind(this))
    )
    this.initializeFloorStates()
    this.updateFloorSweepData()
    this.updateHidden()
  }
  updateNavigable() {
    const e = this.isEditMode()
    const t = this.isViewingAlignedPano()
    this.states.keys.forEach(i => {
      const n = this.getState(i)
      n.navigable = !!e || (t ? n.hasEnabledAlignedSweeps : n.hasEnabledAlignedSweeps || n.hasEnabledUnalignedSweeps)
      n.commit()
    })
    const i: string[] = []
    this.floors.iterate(e => {
      this.getState(e.id).navigable && i.push(e.id)
    })
    this._navigableFloorIds.replace(i)
  }
  updateHidden() {
    const e = !this.currentFloorId
    const t = this.isViewingAlignedPano()
    this.states.keys.forEach(i => {
      const n = !!i && i === this.currentFloorId
      const s = this.getState(i)
      s.hidden = !(e || n || t)
      s.commit()
    })
  }
  updateFloorSweepData() {
    const e = this.sweepData
    this.isEditMode() ||
      (this.states.values.forEach(e => {
        e.hasEnabledAlignedSweeps = !1
        e.hasEnabledUnalignedSweeps = !1
      }),
      e.iterate(e => {
        if (null !== e.floorId) {
          let t = this.getState(e.floorId)
          t || (t = this.initializeFloorState(e.floorId)),
            e.alignmentType === sweepAlignmentEnum.ALIGNED
              ? t.hasEnabledAlignedSweeps || (t.hasEnabledAlignedSweeps = e.enabled)
              : t.hasEnabledUnalignedSweeps || (t.hasEnabledUnalignedSweeps = e.enabled)
          t.commit()
          this.hasEnabledAlignedSweeps || (this.hasEnabledAlignedSweeps = e.enabled)
        }
      }))
    this.updateNavigable()
  }
  getState(e: string) {
    return this.states.get(e)
  }
  get navigableFloorIds() {
    return this._navigableFloorIds.values()
  }
  onNavigableFloorIdsChanged(e: any) {
    return this._navigableFloorIds.onChanged(e)
  }
  isViewingAlignedPano() {
    return this.viewmodeData.isInside() && void 0 !== this.sweepData.currentAlignedSweepObject
  }
  isEditMode() {
    return this.applicationData.application === appTypeMin.WORKSHOP
  }
  get currentFloorId() {
    return this.currentFloorObservable.value ? this.currentFloorObservable.value.id : null
  }
  initializeFloorStates() {
    this.floors.iterate(e => this.initializeFloorState(e.id))
  }
  initializeFloorState(e: string) {
    const t = new FloorState()
    this.states.set(e, t)
    return t
  }
}
function u(e, t) {
  return e
}
const p = {
  floorChangesEnabled: () => !0,
  roomNavFeatureEnabled: () => !0
}
import Floor from "../object/Floor"
import ViewmodeData from "./ViewmodeData"
import ApplicationData from "./ApplicationData"
import LocaleModule from "../module/LocaleModule"
import SweepData from "./SweepData"
import FloorsData from "./FloorsData"
import { Subscription } from "../utils/Subscription"
interface viewDataItem {
  id: string
  index: number
  name: string
}
export default class FloorsViewData extends Data {
  floorSelectable: boolean
  currentFloorObservable: ObservableValue<Floor>
  protected _observableFloorsSelectMode: ObservableValue<boolean>
  protected _observableRoomSelectMode: ObservableValue<boolean>
  protected _showFloorSelection: ObservableValue<boolean>
  floors: FloorsData
  stateHelper: any
  derivedData: Record<string, viewDataItem>
  config: any
  localize: any
  protected _transition: { from: any; to: any; progress: AnimatedNumber; promise: Promise<void> }
  constructor(floors: FloorsData, viewmode: ViewmodeData, sweep: SweepData, app: ApplicationData, localize?: LocaleModule["t"], config?: any) {
    super()
    this.name = "floors-view"
    this.floorSelectable = !1
    this.currentFloorObservable = new ObservableValue(null)
    this._observableFloorsSelectMode = new ObservableValue(!1)
    this._observableRoomSelectMode = new ObservableValue(!1)
    this._showFloorSelection = new ObservableValue(!1)
    this.floors = floors
    this.config = config || p
    this.localize = localize || u
    this.derivedData = {}
    this.getFloorMin = this.getFloorMin.bind(this)
    this.isHidden = this.isHidden.bind(this)
    this.isNavigable = this.isNavigable.bind(this)
    this.getHighestVisibleFloor = this.getHighestVisibleFloor.bind(this)
    this.getHighestVisibleFloorId = this.getHighestVisibleFloorId.bind(this)
    this.updateViewData = this.updateViewData.bind(this)
    this.getViewData = this.getViewData.bind(this)

    this.getAllViewData = this.getAllViewData.bind(this)
    this.getFloor = this.getFloor.bind(this)

    this._transition = {
      from: null,
      to: null,
      progress: new AnimatedNumber(0),
      promise: Promise.resolve()
    }
    this.stateHelper = new FloorsStateHelper(floors, viewmode, sweep, app, this.currentFloorObservable)
    this.updateViewData()
  }
  getFloorMin(e?) {
    const t = e || this.currentFloorId || this.bottomFloorId
    return this.floors.getFloor(t).bottom
  }
  getFloor(e) {
    return this.floors.getFloor(e)
  }
  getAllViewData() {
    const e = []
    this.floors.iterate(t => {
      e.push(this.getViewData(t.id))
    })
    return e
  }
  getViewData(e: string) {
    if (!this.derivedData[e]) {
      const t = this.floors.getFloor(e)
      this.derivedData[e] = {
        id: t.id,
        index: t.index,
        name: this.getFloorName(t.id)
      }
    }
    return this.derivedData[e]
  }
  updateViewData() {
    this.floors.iterate(e => {
      this.derivedData[e.id] = {
        id: e.id,
        index: e.index,
        name: this.getFloorName(e.id)
      }
    })
    this.commit()
  }
  getHighestVisibleFloorId() {
    return this.getHighestVisibleFloor().id
  }
  getHighestVisibleFloor() {
    return this.currentFloor ? this.currentFloor : this.floors.getTopFloor()
  }
  isNavigable(e) {
    return this.stateHelper.getState(e).navigable
  }
  isHidden(e) {
    return this.stateHelper.getState(e).hidden
  }
  isCurrentOrAllFloors(e) {
    return !e || !this.currentFloorId || e === this.currentFloorId
  }
  makeFloorChangeSubscription(e) {
    return this.currentFloorObservable.onChanged(e)
  }
  get currentFloor() {
    return this.currentFloorObservable.value
  }
  get currentFloorId() {
    return this.currentFloorObservable.value?.id || null
  }
  get bottomFloorId() {
    return this.floors.getBottomFloor().id
  }
  get topFloorId() {
    return this.floors.getTopFloor().id
  }
  get singleFloor() {
    if (1 === this.floors.getFloorCount()) return this.floors.getFloorAtIndex(0)
    return null
  }
  get nearestFloor() {
    let e
    return (
      (e = this.transitionActive ? (this.transition.progress.value > 0.5 ? this.transition.to : this.transition.from) : this.currentFloorId),
      e ? this.floors.getFloor(e) : void 0
    )
  }
  get transitionActive() {
    return this.transition.progress.active
  }
  get transition() {
    return this._transition
  }
  transitionToFloorInstant(e) {
    ;(this.currentFloorObservable.value = e ? this.floors.getFloor(e) : null), this.commit()
  }
  transitionToFloor(e, t, i, n) {
    const s = this._transition.progress
    s.modifyAnimation(0, 1, i)
    this._transition = { from: e, to: t, progress: s, promise: n }
    this.commit()
    n.then(() => {
      this.transitionToFloorInstant(t)
    })
  }
  get totalFloors() {
    return this.floorsEnabled ? this.floors.getFloorCount() : 1
  }
  hasEnabledAlignedSweeps(e) {
    return null !== e ? this.stateHelper.getState(e).hasEnabledAlignedSweeps : this.stateHelper.hasEnabledAlignedSweeps
  }
  getNavigableFloorIds() {
    return this.stateHelper.navigableFloorIds
  }
  onNavigableFloorIdsChanged(e) {
    return this.stateHelper.onNavigableFloorIdsChanged(e)
  }
  getFloorIdMap() {
    const e = {}
    return (
      this.iterate(t => {
        e[t.id] = { id: t.id, name: t.name, items: [] }
      }),
      e
    )
  }
  iterate(e: (v?: viewDataItem) => void) {
    this.floors.iterate(t => {
      const i = this.getViewData(t.id)
      i && e(i)
    })
  }
  getFloorNames() {
    const e = []
    return this.floorsEnabled
      ? (this.floors.iterate(t => {
          e[t.index] = this.getFloorName(t.id)
        }),
        e)
      : e
  }
  getFloorName(e: string) {
    if (!e) return this.localize(LangKey.FLOOR_ALL)
    const t = this.floors.getFloor(e)
    return void 0 !== t.name && "" !== t.name ? t.name : this.getDefaultFloorName(e)
  }
  getDefaultFloorName(e: string) {
    const t = this.floors.getFloor(e)
    return this.localize(LangKey.SHOWCASE.FLOORS.DEFAULT_NAME, t.index + 1)
  }
  getFloorsVisibility() {
    if (this.currentFloorId) {
      const e = []
      return (
        this.floors.iterate(t => {
          e[t.index] = t.id === this.currentFloorId ? 1 : 0
        }),
        e
      )
    }
    return []
  }
  get floorsEnabled() {
    return this.config.floorChangesEnabled()
  }
  get floorSelectModeEnabled() {
    return this.config.roomNavFeatureEnabled()
  }
  get floorSelectModeActive() {
    return this._observableFloorsSelectMode.value
  }
  set floorSelectModeActive(e) {
    const t = e && this.floorsEnabled && this.floorSelectModeEnabled
    t !== this._observableFloorsSelectMode.value && ((this._observableFloorsSelectMode.value = t), this.commit())
  }
  onFloorSelectModeChange(e) {
    return this._observableFloorsSelectMode.onChanged(e)
  }
  get showFloorSelection() {
    return this._showFloorSelection.value
  }
  set showFloorSelection(e) {
    ;(e && this.floorSelectModeEnabled) !== this._showFloorSelection.value &&
      ((this._showFloorSelection.value = e && this.floorSelectModeEnabled), this.commit())
  }
  onShowFloorSelectionChanged(e) {
    return this._showFloorSelection.onChanged(e)
  }
  get roomSelectModeActive() {
    return this._observableRoomSelectMode.value
  }
  set roomSelectModeActive(e) {
    const t = (e && this.floorSelectModeEnabled) || !this.floorSelectModeEnabled
    t !== this._observableRoomSelectMode.value && ((this._observableRoomSelectMode.value = t), this.commit())
  }
  onRoomSelectModeChange(e) {
    return this._observableRoomSelectMode.onChanged(e)
  }
}
